﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using CommunityToolkit.Mvvm;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;


namespace BaseHeightControl
{
    /// <summary>
    /// 我想把这个叫做箱体，或者称为轿厢。
    /// </summary>
    public partial class BoxBody: ObservableObject
    {
        /// <summary>
        /// 轿厢名称
        /// </summary>
        [ObservableProperty]
        public string _Name;
        /// <summary>
        /// 轿厢描述，可以介绍轿厢的用途等。
        /// </summary>
        [ObservableProperty]
        public string _Description;
        /// <summary>
        /// 轿厢高度
        /// </summary>
        [ObservableProperty]
        public decimal _BoxHeight;
        /// <summary>
        /// 轿厢传感器高度（相对轿厢地板）
        /// </summary>
        [ObservableProperty]
        public decimal _BaseSensorHeight = 0;
        /// <summary>
        /// 轿厢当前高度（数据来源自传感器）
        /// </summary>
        [ObservableProperty]
        public decimal _CurrentHeight_FromSensor = 0;
        /// <summary>
        /// 轿厢目标高度（数据来源自控制）
        /// </summary>
        [ObservableProperty]
        public decimal _TargetHeight_FromControl = 0;
        /// <summary>
        /// 电梯内部面板触发的目标楼层列表，这个是在电梯里面按按钮进行触发的。
        /// </summary>
        [ObservableProperty]
        public List<int> _TargetFloorNumbers = new List<int>();
        /// <summary>
        /// 轿厢门是否打开
        /// </summary>
        [ObservableProperty]
        public bool _IsDoorOpen = false;
        /// <summary>
        /// 是否是开发模式，可以在这种模式下进行独立调试，或者让门常开。
        /// </summary>
        [ObservableProperty]
        public bool _IsDevelopmentMode = false;
        /// <summary>
        /// 在建筑中的楼层名称，这个数据靠运算得出。
        /// 【需要运算】
        /// </summary>
        [ObservableProperty]
        public string _CurrentNameOfFloor_In_Building = "未运算";
        /// <summary>
        /// 电梯运行状态趋势，向上、向下、停止
        /// </summary>
        [ObservableProperty]
        public string _CurrentStatus_In_Building = "?";
        /// <summary>
        /// 运行速度
        /// </summary>
        [ObservableProperty]
        public decimal _Speed_In_Seconds = 1m;

        /// <summary>
        /// 内部变量，记录上一次自动开门时的楼层
        /// </summary>
        private string lastAtuoOpenDoorFloorNumbers = "";



        #region 内部点击楼层按钮记录操作
        /// <summary>
        /// 2025年10月28日11:41:58
        /// 电梯内部点击控制面板按钮时，所显示的楼层列表。
        /// </summary>
        [ObservableProperty]
        public List<int> _ControlPanel_FloorNumbers = new List<int>() ;

        /// <summary>
        /// 内部计算
        /// </summary>
        private void ControlPanel_JiSuan(int floorNumber)
        {
            if (ControlPanel_FloorNumbers.Contains(floorNumber))
            {
                ControlPanel_FloorNumbers.Remove(floorNumber);
            }
            else
            {
                ControlPanel_FloorNumbers.Add(floorNumber);
            }
            OnPropertyChanged("ControlPanel_FloorNumbers");
        }
        #endregion




        [RelayCommand]
        public void DeveloperButton_On(object parameter)
        { 
            IsDevelopmentMode = !IsDevelopmentMode;
        }

        [RelayCommand]
        public void ClickFloorNumber(object parameter)
        {
            ControlPanel_JiSuan((int)parameter);
            //ReBackData_InBoxBody?.Invoke($"{Name},在楼层控制面板中点击了,{parameter}");
        }
        /// <summary>
        /// 打开控制楼层的面板界面
        /// </summary>
        /// <param name="parameter"></param>
        [RelayCommand]
        public void OpenFloorControl(object parameter)
        {
            ReBackData_InBoxBody?.Invoke($"{Name},楼层控制面板打开!");
        }

        public delegate void ReBackDatas_InBody(string Msg = "");
        public event ReBackDatas_InBody? ReBackData_InBoxBody;

        /// <summary>
        /// 构造函数，我准备在这里面做一个计时器，因为电梯是要动的。
        /// 2025年10月23日14:24:11
        /// </summary>
        public BoxBody()
        {
            System.Timers.Timer timer = new System.Timers.Timer();
            timer.Interval = 100; // 设定时间间隔为0.1秒（100毫秒）
            timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
            timer.Start(); // 启动计时器
        }

        int openDoor_TimeCount = 0;
        private void timer_Elapsed(object? sender, ElapsedEventArgs e)
        {
            if (IsDoorOpen)//如果门打开，则不执行移动逻辑。
            {
                //
                openDoor_TimeCount++;
                if (openDoor_TimeCount > 100)//门打开10秒后，自动关上。
                {
                    IsDoorOpen = false;
                    OnPropertyChanged("IsDoorOpen");
                }
            }
            else
            {
                openDoor_TimeCount = 0;
                //门没开，执行移动逻辑。
                if (CurrentHeight_FromSensor > TargetHeight_FromControl)
                {
                    //下行
                    CurrentHeight_FromSensor = CurrentHeight_FromSensor - Speed_JiSuan();
                    ReBackData_InBoxBody?.Invoke("↓请重新计算楼层");
                }
                else if (CurrentHeight_FromSensor < TargetHeight_FromControl)
                {
                    //上行
                    CurrentHeight_FromSensor = CurrentHeight_FromSensor + Speed_JiSuan();
                    ReBackData_InBoxBody?.Invoke("↑请重新计算楼层");
                }
                else
                {
                    // 这个逻辑是：如果传感器高度和目标高度相等，则停止移动。
                    if (lastAtuoOpenDoorFloorNumbers != CurrentNameOfFloor_In_Building)
                    {
                        lastAtuoOpenDoorFloorNumbers = CurrentNameOfFloor_In_Building;
                        // 需要把这件事告诉外面，咱们动起来了，停止了，接下来要干什么，得由外部告诉咱们。2025年10月23日14:46:22
                        IsDoorOpen = true;//自动开门
                        OnPropertyChanged("IsDoorOpen");
                    }
                    
                    DoorOpen_Clear_MianBanFloor();//到达楼层了，看看自身面板上有没有这个按钮被触发，清除掉吧。2025年11月7日10:40:08
                    ReBackData_InBoxBody?.Invoke($"{Name},到达目标楼层,{CurrentNameOfFloor_In_Building}");
                }
            }
            
        }

        

        decimal jianSuQi = 1.00m;
        private decimal Speed_JiSuan()
        {
            if (Math.Abs(CurrentHeight_FromSensor - TargetHeight_FromControl) < 2)
            {
                if (jianSuQi - 0.1m > 0)
                {
                    jianSuQi = jianSuQi - 0.1m;
                }

                //距离差小于2米，要减速
                return Speed_In_Seconds * jianSuQi;

            }
            else
            {
                jianSuQi = 1.00m;
                //正常速度
                return Speed_In_Seconds * jianSuQi;
            }
        }
        /// <summary>
        /// 内部逻辑运算，看看这部电梯该干嘛。
        /// 运算它下一步该去哪个楼层。
        /// </summary>
        /// <param name="floors">把楼层列表传递进来便于运算目标楼层高度</param>
        public void LogicToDo(List<Floor> floors)
        {
            //通过  该电梯当前所处的楼层、当前运行趋势、内部面板点击的楼层列表，决定其下一步应该去哪里。--->>注意，这只是一个初步的结果，后续还要看楼层按钮的调用情况。 

            //电梯当前所处的楼层         CurrentNameOfFloor_In_Building
            //当前运行趋势               CurrentStatus_In_Building
            //内部面板点击的楼层列表     ControlPanel_FloorNumbers


            var currentNameOfFloor = CurrentNameOfFloor_In_Building.Split("楼")[0];

            #region 开始运算。
            switch (CurrentStatus_In_Building)
            {
                case "↑":
                    {
                        //向上运行趋势
                        var upFloors = ControlPanel_FloorNumbers.Where(f => f > Convert.ToInt32(currentNameOfFloor)).OrderBy(f => f).ToList();
                        if (upFloors.Count > 0)
                        {
                            //有向上运行的楼层
                            TargetHeight_FromControl = JiSuanMubiaoGaoDu(floors, upFloors.Min());//取最小的那个楼层,并计算出目标高度  2025年11月7日10:16:07
                        }
                        else
                        {
                            //没有向上运行的楼层，看看有没有向下运行的楼层
                            var downFloors = ControlPanel_FloorNumbers.Where(f => f < Convert.ToInt32(currentNameOfFloor)).OrderBy(f => f).ToList();
                            if (downFloors.Count > 0)
                            {
                                TargetHeight_FromControl = JiSuanMubiaoGaoDu(floors, downFloors.Max()); //取最大的那个楼层，并计算出目标高度 2025年11月7日10:21:47
                            }
                            else
                            {
                                //没有任何楼层请求，停止。
                                TargetHeight_FromControl = CurrentHeight_FromSensor;
                            }

                            //此处的运行趋势虽然发生了变化，但现在不要动，等待程序自动进行运算。 ↑↑↑↑↑
                        }
                    }
                    break;
                case "↓":
                    {
                        //向下运行趋势
                        var downFloors = ControlPanel_FloorNumbers.Where(f => f < Convert.ToInt32(currentNameOfFloor)).OrderBy(f => f).ToList();
                        if (downFloors.Count > 0)
                        {
                            //有向下运行的楼层
                            TargetHeight_FromControl = JiSuanMubiaoGaoDu(floors, downFloors.Max());//取最大的那个楼层，并计算出目标高度 2025年11月7日10:16:07
                        }
                        else
                        {
                            //没有向下运行的楼层，看看有没有向上运行的楼层
                            var upFloors = ControlPanel_FloorNumbers.Where(f => f > Convert.ToInt32(currentNameOfFloor)).OrderBy(f => f).ToList();
                            if (upFloors.Count > 0)
                            {
                                TargetHeight_FromControl = JiSuanMubiaoGaoDu(floors, upFloors.Min()); //取最小的那个楼层，并计算出目标高度 2025年11月7日10:21:47
                            }
                            else
                            {
                                //没有任何楼层请求，停止。
                                TargetHeight_FromControl = CurrentHeight_FromSensor;
                            }

                            //此处的运行趋势虽然发生了变化，但现在不要动，等待程序自动进行运算。 ↑↑↑↑↑
                        }
                    }
                    break;
                case "-":
                    {
                        //既然现在都停了，说明没有任何内部按钮了吧。那么，现在谁按了，我就走一个呗。2025年11月7日10:37:07
                        if (ControlPanel_FloorNumbers.Count > 0)
                        {
                            TargetHeight_FromControl = JiSuanMubiaoGaoDu(floors, ControlPanel_FloorNumbers[0]);
                        }
                    }
                    break;
                default:
                    break;
            }

            #endregion

        }
        private void DoorOpen_Clear_MianBanFloor()
        {
            //通过  该电梯当前所处的楼层、内部面板点击的楼层，做处理，把当前电梯所处的楼层在面板中进行查询，发现了，就移除。2025年11月7日10:42:08
            //电梯当前所处的楼层         CurrentNameOfFloor_In_Building
            //内部面板点击的楼层列表     ControlPanel_FloorNumbers


            var currentNameOfFloor = CurrentNameOfFloor_In_Building.Split("楼")[0];
            #region 处理
            for (int i = 0; i < ControlPanel_FloorNumbers.Count; i++)
            {
                if (ControlPanel_FloorNumbers[i]== Convert.ToInt32(currentNameOfFloor))
                {
                    ControlPanel_FloorNumbers.RemoveAt(i);
                    OnPropertyChanged("ControlPanel_FloorNumbers");
                    break;
                }
            }
            #endregion
        }

        private decimal JiSuanMubiaoGaoDu(List<Floor> floors,int floorNumber)
        {
            decimal result = 0m;

            for (int i = 0; i < floors.Count; i++)
            {
                if (floors[i].FloorNumber == floorNumber)
                {
                    result = floors[i].Altitude;
                    break;
                }
            }

            return result;
        }
    }
}
